//
//  ZKBombView.swift
//  Swift-app开发基础架构
//
//  Created by 朱凯 on 2017/10/18.
//  Copyright © 2017年 com.itboye. All rights reserved.
//

import UIKit

// MARK: 枚举
// 内容类型（自定义和picker）
enum KZBombContentMode {
    case custom
    case picker
    case datePicker(mode: UIDatePickerMode, date: Date, minDate: Date, maxDate: Date)
}
// 显示的位置
enum KZBombPositionMode {
    case top
    case center
    case bottom
}
// 弹出的位置
enum KZBombPopMode {
    case top
    case center
    case bottom
}

struct KZBombPickerDataSource {
    
    // 组数
    var components: Int = 1

    // 第一组的数据（基础数据）
    var baseContents: [String]
    
    // 根据当前组的索引和上一组选中的行，来获取下一组需要展示的数组，根据两个Int值可以关联前后关系，如果不需要关联，则直接判断第一个Int值（需要返回数组的组的索引）来返回一个数组即可
    var nextContentsFetchClouse: ((_ component: Int,_ prevComponentSelectedRow: Int) -> [String]?)?
    
    // 记录每一组的选中的行
    var selectedRows: [Int]
    
    // 选中回调，数组元素个数是components
    var didSelectedRowsClouse: (([Int]) -> ())?
    
    // 初始化
    init(components: Int, baseContents: [String], nextContentsFetchClouse: ((Int, Int) -> [String]?)? = nil) {
        self.components = components
        self.baseContents = baseContents
        selectedRows = [Int]()
        for _ in baseContents {
            selectedRows.append(0)
        }
        self.nextContentsFetchClouse = nextContentsFetchClouse
    }
}

// MARK: 主视图
class KZBombView: UIControl, UIPickerViewDelegate, UIPickerViewDataSource {
    
    // MARK: 视图
    var contentView: UIView!
    private var fillView: UIView!
    var fillViewColor: UIColor?

    // MARK: 属性
    // 内容类型
    var content: KZBombContentMode = .custom {
        didSet {
            switch content {
            case .custom:
                return
            case .picker:
                let picker = UIPickerView(frame: CGRect(x: 0, y: 0, width: kScreenWidth, height: 216))
                picker.backgroundColor = UIColor.white
                picker.delegate = self
                contentView = picker
            case .datePicker(let mode, let date, let minDate, let maxDate):
                let picker = UIDatePicker(frame: CGRect(x: 0, y: 0, width: kScreenWidth, height: 216))
                picker.backgroundColor = UIColor.white
                picker.datePickerMode = mode
                picker.date = date
                picker.minimumDate = minDate
                picker.maximumDate = maxDate
                picker.addTarget(self, action: #selector(datePickerDidChangeValue(picker:)), for: .valueChanged)
                contentView = picker
            }
        }
    }
    // 位置类型
    var position: KZBombPositionMode = .bottom
    
    // 弹出方式类型
    var pop: KZBombPopMode = .bottom
    
    // 如果是picker的话需要设置数据源
    var pickerDataSource: KZBombPickerDataSource!
    
    // 如果是datePicker的话需要设置回调
    var datePickerReturnClouse: ((DateComponents?) -> ())?
    
    // MARK: UIPickerViewDelegate
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return pickerDataSource.components
    }
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        
        if component == 0 {
            return pickerDataSource.baseContents.count
        } else {
            if let nextContentsFetchClouse = pickerDataSource.nextContentsFetchClouse {
                let selectedRowAtPrevComponent = pickerDataSource.selectedRows[component - 1]
                let contents = nextContentsFetchClouse(component, selectedRowAtPrevComponent)
                if let contents = contents {
                    return contents.count
                } else {
                    return 0
                }
            } else {
                return 0
            }
        }
    }
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        if component == 0 {
            return pickerDataSource.baseContents[row]
        } else {
            if let nextContentsFetchClouse = pickerDataSource.nextContentsFetchClouse {
                // 找到上一组选中的行
                let selectedRowAtPrevComponent = pickerDataSource.selectedRows[component - 1]
                // 根据这个行和本组的索引来获取数组（外部设置）
                let contents = nextContentsFetchClouse(component, selectedRowAtPrevComponent)
                if let contents = contents {
                    return contents[row]
                } else {
                    return nil
                }
            } else {
                return nil
            }
        }
    }
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        
        // 设置dataSource中选中行的索引
        // 点击了本组，则前置组不需要修改，而后置组要全部设置为0
        for index in component..<pickerDataSource.components {
            if index == component {
                pickerDataSource.selectedRows[component] = row
            } else {
                pickerDataSource.selectedRows[index] = 0
            }
        }
        
        pickerView.reloadAllComponents()
        
        // 设置完每组的选中行以后，对picker做一次UI设置
        for index in 0..<pickerDataSource.components {
            pickerView.selectRow(pickerDataSource.selectedRows[index], inComponent: index, animated: true)
        }
        
        // 回调
        if let didSelectedRowsClouse = pickerDataSource.didSelectedRowsClouse {
            didSelectedRowsClouse(pickerDataSource.selectedRows)
        }
    }
    
    // MARK: 点击事件
    // 时间选择器
    @objc private func datePickerDidChangeValue(picker: UIDatePicker) {
        
        let cal = picker.calendar
        let components = Set<Calendar.Component>(arrayLiteral: .year, .month, .day)
        let dateComponents = cal?.dateComponents(components, from: picker.date)
        
        if let datePickerReturnClouse = datePickerReturnClouse {
            datePickerReturnClouse(dateComponents)
        }
    }
    
    // MARK: 显示和隐藏
    func show() {
        assert(contentView != nil, "内容视图不能为nil")
        switch content {
        case .picker:
            assert(pickerDataSource != nil, "picker必需数据源")
        default:
            break
        }
        
        // 点击背景半透明遮罩视图即隐藏
        let ges = UITapGestureRecognizer.init(target: self, action: #selector(hide))
        self.addGestureRecognizer(ges)
        kWindow.addSubview(self)
        self.backgroundColor = UIColor.black.withAlphaComponent(0)
        
        self.frame = CGRect.init(x: 0, y: 0, width: kWindow.width, height: kWindow.height)

        self.addSubview(contentView)
        
        var showClouse: KZBlock = {}
        
        if position == .bottom {
            
            pop = .bottom

            fillView = UIView()
            fillView.backgroundColor = self.fillViewColor ?? UIColor.white
            fillView.frame = CGRect.init(x: 0, y: 0, width: self.width, height: 0)
            self.addSubview(fillView)
            if #available(iOS 11.0, *) {
                fillView.height = kWindow.safeAreaInsets.bottom
            }
            
            contentView.top = self.height
            contentView.x = width / 2
            fillView.top = contentView.bottom
            showClouse = {
                self.contentView.bottom = self.height - self.fillView.height
                self.fillView.top = self.contentView.bottom
            }
        } else if position == .top {
            pop = .top
            
            contentView.bottom = 0
            contentView.x = width / 2
            showClouse = {
                self.contentView.top = 0
            }
        } else {
            if pop == .top {
                contentView.bottom = 0
                showClouse = {
                    self.contentView.center = CGPoint.init(x: self.width / 2, y: self.height / 2)
                }
            } else if pop == .bottom {
                contentView.top = kWindow.height
                fillView.top = contentView.bottom
                showClouse = {
                    self.contentView.center = CGPoint.init(x: self.width / 2, y: self.height / 2)
                }
            } else {
                contentView.center = CGPoint.init(x: self.width / 2, y: self.height / 2)
                contentView.transform = CGAffineTransform.identity.scaledBy(x: 0.1, y: 0.1)
                showClouse = {
                    self.contentView.transform = CGAffineTransform.identity
                }
            }
        }
        
        UIView.animate(withDuration: 0.3) {
            self.backgroundColor = UIColor.black.withAlphaComponent(0.4)
            showClouse()
        }
    }
    
    @objc func hide() {
        
        var hideClouse: KZBlock = {}
        
        if position == .bottom {
            hideClouse = {
                self.contentView.top = kWindow.height
                self.fillView.top = self.contentView.bottom
            }
        } else if position == .top {
            hideClouse = {
                self.contentView.bottom = 0
            }
        } else {
            if pop == .top {
                hideClouse = {
                    self.contentView.top = kWindow.height
                }
            } else if pop == .bottom {
                hideClouse = {
                    self.contentView.top = kWindow.height
                }
            } else {
                hideClouse = {
                    self.contentView.transform = CGAffineTransform.identity.scaledBy(x: 0.1, y: 0.1)
                }
            }
        }
        
        UIView.animate(withDuration: 0.3, animations: {
            self.backgroundColor = UIColor.black.withAlphaComponent(0)
            hideClouse()
        }) { (finish) in
            if finish {
                self.removeFromSuperview()
            }
        }
    }
}
